﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace UniRx.Operators
{
	// Token: 0x020003E1 RID: 993
	internal class BatchFrameObservable<T> : OperatorObservableBase<IList<T>>
	{
		// Token: 0x0600146F RID: 5231 RVA: 0x0005C02F File Offset: 0x0005A42F
		public BatchFrameObservable(IObservable<T> source, int frameCount, FrameCountType frameCountType) : base(source.IsRequiredSubscribeOnCurrentThread<T>())
		{
			this.source = source;
			this.frameCount = frameCount;
			this.frameCountType = frameCountType;
		}

		// Token: 0x06001470 RID: 5232 RVA: 0x0005C052 File Offset: 0x0005A452
		protected override IDisposable SubscribeCore(IObserver<IList<T>> observer, IDisposable cancel)
		{
			return new BatchFrameObservable<T>.BatchFrame(this, observer, cancel).Run();
		}

		// Token: 0x04000BC2 RID: 3010
		private readonly IObservable<T> source;

		// Token: 0x04000BC3 RID: 3011
		private readonly int frameCount;

		// Token: 0x04000BC4 RID: 3012
		private readonly FrameCountType frameCountType;

		// Token: 0x020003E2 RID: 994
		private class BatchFrame : OperatorObserverBase<T, IList<T>>
		{
			// Token: 0x06001471 RID: 5233 RVA: 0x0005C061 File Offset: 0x0005A461
			public BatchFrame(BatchFrameObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
			{
				this.parent = parent;
				this.timer = new BatchFrameObservable<T>.BatchFrame.ReusableEnumerator(this);
			}

			// Token: 0x06001472 RID: 5234 RVA: 0x0005C094 File Offset: 0x0005A494
			public IDisposable Run()
			{
				this.list = new List<T>();
				IDisposable disposable = this.parent.source.Subscribe(this);
				return StableCompositeDisposable.Create(disposable, this.cancellationToken);
			}

			// Token: 0x06001473 RID: 5235 RVA: 0x0005C0CC File Offset: 0x0005A4CC
			public override void OnNext(T value)
			{
				object obj = this.gate;
				lock (obj)
				{
					if (!this.isCompleted)
					{
						this.list.Add(value);
						if (!this.isRunning)
						{
							this.isRunning = true;
							this.timer.Reset();
							switch (this.parent.frameCountType)
							{
							case FrameCountType.Update:
								MainThreadDispatcher.StartUpdateMicroCoroutine(this.timer);
								break;
							case FrameCountType.FixedUpdate:
								MainThreadDispatcher.StartFixedUpdateMicroCoroutine(this.timer);
								break;
							case FrameCountType.EndOfFrame:
								MainThreadDispatcher.StartEndOfFrameMicroCoroutine(this.timer);
								break;
							}
						}
					}
				}
			}

			// Token: 0x06001474 RID: 5236 RVA: 0x0005C194 File Offset: 0x0005A594
			public override void OnError(Exception error)
			{
				try
				{
					this.observer.OnError(error);
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x06001475 RID: 5237 RVA: 0x0005C1CC File Offset: 0x0005A5CC
			public override void OnCompleted()
			{
				object obj = this.gate;
				List<T> list;
				lock (obj)
				{
					this.isCompleted = true;
					list = this.list;
				}
				if (list.Count != 0)
				{
					this.observer.OnNext(list);
				}
				try
				{
					this.observer.OnCompleted();
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x04000BC5 RID: 3013
			private readonly BatchFrameObservable<T> parent;

			// Token: 0x04000BC6 RID: 3014
			private readonly object gate = new object();

			// Token: 0x04000BC7 RID: 3015
			private readonly BooleanDisposable cancellationToken = new BooleanDisposable();

			// Token: 0x04000BC8 RID: 3016
			private readonly IEnumerator timer;

			// Token: 0x04000BC9 RID: 3017
			private bool isRunning;

			// Token: 0x04000BCA RID: 3018
			private bool isCompleted;

			// Token: 0x04000BCB RID: 3019
			private List<T> list;

			// Token: 0x020003E3 RID: 995
			private class ReusableEnumerator : IEnumerator
			{
				// Token: 0x06001476 RID: 5238 RVA: 0x0005C250 File Offset: 0x0005A650
				public ReusableEnumerator(BatchFrameObservable<T>.BatchFrame parent)
				{
					this.parent = parent;
				}

				// Token: 0x17000184 RID: 388
				// (get) Token: 0x06001477 RID: 5239 RVA: 0x0005C25F File Offset: 0x0005A65F
				public object Current
				{
					get
					{
						return null;
					}
				}

				// Token: 0x06001478 RID: 5240 RVA: 0x0005C264 File Offset: 0x0005A664
				public bool MoveNext()
				{
					if (this.parent.cancellationToken.IsDisposed)
					{
						return false;
					}
					object gate = this.parent.gate;
					List<T> list;
					lock (gate)
					{
						if (this.currentFrame++ != this.parent.parent.frameCount)
						{
							return true;
						}
						if (this.parent.isCompleted)
						{
							return false;
						}
						list = this.parent.list;
						this.parent.list = new List<T>();
						this.parent.isRunning = false;
					}
					this.parent.observer.OnNext(list);
					return false;
				}

				// Token: 0x06001479 RID: 5241 RVA: 0x0005C340 File Offset: 0x0005A740
				public void Reset()
				{
					this.currentFrame = 0;
				}

				// Token: 0x04000BCC RID: 3020
				private readonly BatchFrameObservable<T>.BatchFrame parent;

				// Token: 0x04000BCD RID: 3021
				private int currentFrame;
			}
		}
	}
}
